define(["dojo/_base/declare",
        "dojo/_base/array",
        "esri/layers/layer",
        "esri/layers/GraphicsLayer",
        "esri/graphic",
        "dojo/dom-construct",
        "dojo/dom-style",
        "esri/domUtils",
        "dojo/_base/connect",
        "dojo/_base/config",
        "esri/geometry/Point",
        "esri/symbols/PictureMarkerSymbol",
        "esri/symbols/SimpleLineSymbol",
        'esri/Color',
        "dojo/on"],
    function (declare, ArrayUtils, Layer, GraphicsLayer, Graphic, DomConstructUtils, DomStyleUtils, DomUtils, ConnectUtils, config, Point, PictureMarkerSymbol
        , SimpleLineSymbol, Color, on) {
        return declare([GraphicsLayer], {
            constructor: function (p) {
                this._element = null; //图层dom元素
                this._connects = []; //事件集合
                this.onLoad(this);
            }
            , _setMap: function (map, svg) {
                var g = this.inherited(arguments);
                var self = this;
                this._map = map;
                this._element = DomConstructUtils.create("div", {
                    style: "position: absolute; left: 0px; top: 0px; right: 0px; bottom: 0px;"
                }, svg.rawNode.parentNode);

                this._connects.push(ConnectUtils.connect(this, "onVisibilityChange", this, this._visibilityChangeHandler));
                this._connects.push(ConnectUtils.connect(map, "onPan", this, this._panHandler));
                this._connects.push(ConnectUtils.connect(map, "onPanEnd", this, this._panEndHandler));
                this._connects.push(ConnectUtils.connect(map, "onZoomStart", this, this._zoomStartHandler));
                this._connects.push(ConnectUtils.connect(map, "onZoomEnd", this, this._zoomEndHandler));
                this._connects.push(ConnectUtils.connect(self, "onClick", this, this._clickHandler))
                return g;
            }
            , _unsetMap: function (map, container) {
                this.inherited(arguments);

                //销毁所有事件
                ArrayUtils.forEach(this._connects, ConnectUtils.disconnect, this);

                //销毁dom
                if (this._element) {
                    //container.removeChild(this._element);
                    this._element.parentNode.removeChild(this._element);
                }
                ;

                //销毁变量
                this._map = null;
                this._element = null;
                this._connects = null;
            }
            , __refresh: function () {
                this.refresh();
            }
            , _visibilityChangeHandler: function (visible) {
                if (visible) {
                    DomUtils.show(this._element);
                } else {
                    DomUtils.hide(this._element);
                }
                ;
            }
            , _panHandler: function (delta, extent) {
                //平移时计算移动坐标差
                DomStyleUtils.set(this._element, {
                    "transform": "translate(" + extent.x + "px, " + extent.y + "px)"
                });
            }
            , _draw: function (graphic) {
                var map = this.getMap();
                if (map == null) {
                    return;
                }
                ;

                if (graphic._element == null) {
                    return;
                }
                ;

                graphic._element.style.visibility = 'hidden';

                this._element.appendChild(graphic._element);

                var width = graphic._element.offsetWidth;
                var height = graphic._element.offsetHeight;

                if (!graphic.symbol && width > 0 && height > 0) {
                    graphic.symbol = new PictureMarkerSymbol(this.imageUrl, width, height);

                }
                ;
                this.inherited(arguments);

                if (graphic._element.__remove) {
                    graphic._element.parentNode.removeChild(graphic._element);
                    return;
                }
                ;

                graphic._element.style.visibility = "visible";


                var minPoint = new Point(map.extent.xmin, map.extent.ymin, map.spatialReference);
                var maxPoint = new Point(map.extent.xmax, map.extent.ymax, map.spatialReference);
                var screenMinPoint = map.toScreen(minPoint);
                var screenMaxPoint = map.toScreen(maxPoint);
                try {
                    var x = graphic.geometry.x;
                    var y = graphic.geometry.y;
                } catch (e) {

                    console.log(e)
                }


                var left = (x - minPoint.x) / (maxPoint.x - minPoint.x) * screenMaxPoint.x;
                var top = (1 - (y - minPoint.y) / (maxPoint.y - minPoint.y)) * screenMinPoint.y;

                left = left - width / 2;
                top = top - height / 2;

                DomStyleUtils.set(graphic._element, {
                    left: left + "px",
                    top: top + "px"
                });

            }
            , _panEndHandler: function (delta, extent) {
                //平移结束恢复坐标
                DomStyleUtils.set(this._element, {
                    "transform": "translate(0px, 0px)"
                });
            }
            , _zoomStartHandler: function (anchor, extent, level, zoomFactor) {
                DomUtils.hide(this._element);
            }
            , _zoomEndHandler: function (extent, v, point, level) {
                var self = this;
                if (self._currentLevel && self._currentLevel > level) {
                    self.parentCantonCode = '';
                }
                ;
                self._currentLevel = level;
                self.refresh();
                DomUtils.show(this._element);
            }
            , _clickHandler: function (evt) {
                var self = this;
                var map = self._map;
                var g = evt.graphic
                var attr = g.attributes;
                var point = g.geometry;
                self.parentCantonCode = attr[self.cantonCodeFieldName];
                var cantonLevelObj = self.cantonLevelDictionary[attr[self.cantonLevelFieldName] + 1];

                if (cantonLevelObj) {
                    map.setScale(cantonLevelObj.min);
                };
                map.centerAt(point);
                if (typeof self.clickCallback=="function") {
                    var e = {_esriEvent: evt};
                    e.data = attr;
                    self.clickCallback({data: attr, _esriEvent: e});
                }
                ;
            }
            , clear: function () {
                this.inherited(arguments);
                var childs = this._element.childNodes;
                for (var i = childs.length - 1; i >= 0; i--) {
                    this._element.removeChild(childs[i]);
                }
                ;
            }
            , refresh: function () {
                var self = this;
                var map = this.getMap();
                if (map == null) {
                    return;
                }
                ;
                self.clear();
                if (!self.data || self.data.length < 1) {
                    return
                }
                var mapScale = map.getScale();
                var cantonCode = self.parentCantonCode || '';
                self.data.map(function (item) {
                    var cantonLevelObj = self.cantonLevelDictionary[item[self.cantonLevelFieldName]];
                    if (cantonLevelObj) {
                        if (cantonCode&&item[self.parentCantonCodeFieldName]) {
                            if (cantonCode == item[self.parentCantonCodeFieldName]) {
                                filterMapScale(cantonLevelObj, item);
                            };
                        } else {
                            filterMapScale(cantonLevelObj, item);
                        }
                        ;
                    }
                });

                function filterMapScale(cantonLevelObj, item) {
                    if (cantonLevelObj.min && cantonLevelObj.max) {
                        if (cantonLevelObj.min > mapScale && cantonLevelObj.max <= mapScale) {
                            var divGraphic = self._creatDivGraphic(item);
                            self.add(divGraphic);
                        }
                    } else if (cantonLevelObj.min) {
                        if (cantonLevelObj.min > mapScale) {
                            var divGraphic = self._creatDivGraphic(item);
                            self.add(divGraphic);
                        }
                    } else if (cantonLevelObj.max) {
                        if (cantonLevelObj.max <= mapScale) {
                            var divGraphic = self._creatDivGraphic(item);
                            self.add(divGraphic);
                        }
                    }
                }
            }
            , _creatDivGraphic: function (item) {
                var map = this.getMap();
                if (map == null) {
                    return;
                }
                ;
                var pointGeometry = new Point(item[this.lngFieldName], item[this.latFieldName], map.spatialReference);
                var graphic = new Graphic(pointGeometry);
                var fieldArray = this.fieldArray;

                if (!item.html) {
                    item.html = `<div class="${(item.symbol && item.symbol.class) || this.class}" style="${(item.symbol && item.symbol.style) || this.style}">`
                    if (item.symbol && item.symbol.html) {
                        item.html += item.symbol.html;
                    } else if (fieldArray && fieldArray.length > 0) {
                        fieldArray.map(function (entity) {
                            var value = item[entity.key];
                            var style = entity.style || '';
                            if (value || value == 0) {
                                item.html += `<div style="${style}">${value}</div>`
                            }
                        })
                    }
                    item.html += '</div>';
                }
                ;
                graphic._element = DomConstructUtils.create("div", {
                    style: "position: absolute; left: 0px; top: 0px;"
                });
                graphic._element.innerHTML = item.html;
                graphic.attributes = item;
                return graphic;
            }
            , _getElementStyle: function () {
                return this.style;
            }
            , setElementStyle: function (value) {
                this.style = value;
            }
        })
    });